#include "ExchangeAdapterConfig.h"
#include "SHMarketDataProvider.h"
#include "SHMarketDataHandler.h"
#define TIXML_USE_STL
#include "tinyxml.h"

namespace exchangeadapter_shanghai
{
	CSHMarketDataProvider::CSHMarketDataProvider(void)
	{
	}

	CSHMarketDataProvider::~CSHMarketDataProvider(void)
	{
	}

	std::string CSHMarketDataProvider::GetName()
	{
		return "ShangHaigMarketDataProvider";
	}
	
	void CSHMarketDataProvider::OnRspMsg(const FIX::Message &msg)
	{
		OnResponseMsg(msg);
	}

	bool CSHMarketDataProvider::Initialize(void* pParam)
	{
		InitParam* pInitparam = (InitParam*)pParam;
		pUserApi = CShfeFtdcMduserApi::CreateFtdcMduserApi(
			pInitparam->sFlowPath.c_str());
		CSHMarketDataHandler::InitParam handlerparam;
		handlerparam.ParticipantID = pInitparam->sParticipantID;
		handlerparam.UserID = pInitparam->sUserID;
		handlerparam.Password = pInitparam->sPassword;
		pPriceHandler = boost::shared_ptr<CSHMarketDataHandler>(
			new CSHMarketDataHandler(this,pUserApi,handlerparam));
		pUserApi->RegisterSpi(pPriceHandler.get());
		switch(pInitparam->iResumeType){
		case 0: pUserApi-> SubscribeMarketDataTopic (100, TERT_RESTART);break;
		case 1: pUserApi-> SubscribeMarketDataTopic (100, TERT_RESUME);break;
		case 2:
		default:pUserApi-> SubscribeMarketDataTopic (100, TERT_QUICK);break;
		}

		for(int i = 0;i < (int)(pInitparam->sAddressIps.size());i++){
			std::string straddr = pInitparam->sAddressIps[i];
			int iport = pInitparam->iPorts[i];
			char addressinfo[64];
			sprintf(addressinfo,"tcp://%s:%d",straddr.c_str(),iport);
			pUserApi->RegisterFront(addressinfo);
		}

		pUserApi->Init();
		return true;
	}

	void CSHMarketDataProvider::UnInitialize()
	{
		pUserApi->Release();
	}

	bool CSHMarketDataProvider::SupportDoM()
	{
		return true;
	}

	bool CSHMarketDataProvider::InitializeByXML( const char* configfile )
	{
		std::pair<bool,CSHMarketDataProvider::InitParam> param = 
			CSHMarketDataProvider::InitParam::LoadConfig(configfile);
		if (param.first)
			return Initialize(&param.second);
		else
			return false;		
	}

	bool CSHMarketDataProvider::Login(void* ppara)
	{
		uint32 seqnum = (uint32)(ppara);
		CShfeFtdcReqUserLoginField reqUserLogin;
		std::strcpy(reqUserLogin.ParticipantID,
			pPriceHandler->m_param.ParticipantID.c_str());
		std::strcpy(reqUserLogin.UserID,
			pPriceHandler->m_param.UserID.c_str());
		std::strcpy(reqUserLogin.Password,
			pPriceHandler->m_param.Password.c_str());
		std::strcpy(reqUserLogin.UserProductInfo, "RMMSoft(v1.0.0)");

		if(0 > pUserApi->ReqUserLogin(&reqUserLogin,seqnum))
			return false;
		return true;
	}

	bool CSHMarketDataProvider::Logout(void* ppara)
	{
		uint32 seqnum = (uint32)(ppara);
		CShfeFtdcReqUserLogoutField reqUserLogout;
		std::strcpy(reqUserLogout.ParticipantID,
			pPriceHandler->m_param.ParticipantID.c_str());
		std::strcpy(reqUserLogout.UserID,pPriceHandler->m_param.UserID.c_str());

		if(0 > pUserApi->ReqUserLogout(&reqUserLogout,seqnum))
			return false;
		return true;
	}
	
	std::pair<bool,CSHMarketDataProvider::InitParam> 
		CSHMarketDataProvider::InitParam::LoadConfig(const std::string& fname)
	{
		CSHMarketDataProvider::InitParam param;

		TiXmlDocument doc(fname);
		bool loadOkay = doc.LoadFile();
		if (!loadOkay)
			return std::make_pair(false,param);

		TiXmlNode* pNode = doc.FirstChild("configure");
		TiXmlNode* ele = pNode->FirstChild("sflowpath");
		param.sFlowPath = ele->FirstChild()->Value();
		ele = ele->NextSibling();

		TiXmlNode* addressNode;
		while(ele != NULL){
			if(ele->ValueStr() == "saddress"){
				addressNode = ele->FirstChild("saddressip");
				param.sAddressIps.push_back(addressNode->FirstChild()->Value());
				addressNode = ele->FirstChild("iport");
				param.iPorts.push_back(atoi(
					addressNode->FirstChild()->Value()));
			}
			ele = ele->NextSibling();
		}
		ele = pNode->FirstChild("sparticipantid");
		param.sParticipantID = ele->FirstChild()->Value();
		ele = pNode->FirstChild("suserid");
		param.sUserID = ele->FirstChild()->Value();
		ele = pNode->FirstChild("spassword");
		param.sPassword = ele->FirstChild()->Value();
		ele = pNode->FirstChild("iresumeType");
		param.iResumeType = atoi(ele->FirstChild()->Value());

		return std::make_pair(true,param);
	}
}